﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team (cellcloudproject@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellFileExpress_h
#define CellFileExpress_h

#include "CellPrerequisites.h"
#include "CellFileExpressListener.h"
#include "CellFileExpressDefinition.h"
#include "CellMessageHandler.h"
#include "CellExecutorListener.h"
#include "CellInet4Address.h"
#include "CellInet6Address.h"
#include "CellStringVector.h"

namespace cell
{

// 快递授权码
class ExpressAuthCode;

// 任务监听器
class ExpressTaskListener;


/** 文件传输服务类。
@author
	Jiangwei Xu
*/
class _CellExport FileExpress : public MessageHandler,
	public ExecutorListener, public GeneralAlloc
{
public:
	/** 构造函数。
	*/
	FileExpress(void);

	/** 析构函数。
	*/
	virtual ~FileExpress(void);

public:
	/** 启动为服务器模式。
	*/
	void startServer(uint port = FE_PORT);

	/** 关闭服务器模式。
	*/
	void stopServer(void);

	/** 添加授权码。
	*/
	void addAuthCode(const ExpressAuthCode& code);

	/** 移除授权码。
	*/
	void removeAuthCode(const String& authCode);

	/** 下载文件。
	*/
	bool download(const InetAddress* address, const String& fileName,
		const String& localPath, const String& authCode);

	/**
	@return 启动上传操作是否成功。
	*/
	bool upload(const InetAddress* address, const String& fullPath, const String& authCode);

	/** 放弃上载/下载操作。
	*/
	void abort(const String& authCode);

	/** 添加监听器。
	*/
	void addListener(FileExpressListener* listener);

	/** 移除监听器。
	*/
	void removeListener(FileExpressListener* listener);

	/** 传输任务是否完成。
	*/
	bool hasTaskDone(const String& authCode);

private:
	/** 维护伺服上下文。
	*/
	void maintainSevoContext(void);

	/**
	*/
	void interpret(Session* session, Packet* packet);

	/**
	*/
	void authenticate(Session* session, Packet* packet);

	/**
	*/
	void responseAttribute(Session* session, Packet* packet);

	/**
	*/
	void responseBegin(Session* session, Packet* packet);

	/**
	*/
	void responseEnd(Session* session, Packet* packet);

	/**
	*/
	void responseOffer(Session* session, Packet* packet);

	/**
	*/
	void responseData(Session* session, Packet* packet);

	/**
	*/
	void responseDataReceipt(Session* session, Packet* packet);

	/**
	*/
	bool checkSession(Session* session, const String& authCode);

	/**
	*/
	void reject(Session* session);

	/**
	*/
	void interrupt(Session* session);

	/**
	*/
	void fireExpressStarted(FileExpressContext* ctx);

	/**
	*/
	void fireExpressCompleted(FileExpressContext* ctx);

	/**
	*/
	void fireExpressProgress(FileExpressContext* ctx);

	/**
	*/
	void fireExpressError(FileExpressContext* ctx);

protected:
	/** 创建连接会话。
	*/
	void sessionCreated(Session* session);

	/** 销毁连接会话。
	*/
	void sessionDestroyed(Session* session);

	/** 开启连接会话。
	*/
	void sessionOpened(Session* session);

	/** 关闭连接会话。
	*/
	void sessionClosed(Session* session);

	/** 接收到消息。
	*/
	void messageReceived(Session* session, Message* message);

	/** 消息已发送。
	*/
	void messageSent(Session* session, Message* message);

	/** 发生程序错误。
	*/
	void errorOccurred(uint16 errorCode, Session* session);

	/** 执行任务已就绪。
	*/
	void prepared(Runnable* command);

	/** 执行器执行任务完毕。
	*/
	void executed(Runnable* command);

private:
	/** 会话工作记录
	*/
	class _CellPrivate SessionRecord : public GeneralAlloc
	{
	public:
		SessionRecord(void);
		SessionRecord(const SessionRecord& other);
		virtual ~SessionRecord(void);

	public:
		void addAuthCode(const String& authCode);
		void removeAuthCode(const String& authCode);
		void addFileName(const String& fileName);
		void removeFileName(const String& fileName);

		bool containsAuthCode(const String& authCode);

		const StringVector& getAuthCodeList(void) const;
		const StringVector& getFileNameList(void) const;

	private:
		StringVector mAuthCodes;
		StringVector mFileNames;
	};

	// 同一个上下文能服务多个 Session

	typedef HashMap<ulong, SessionRecord*> SessionRecords;
	typedef HashMap<String, ExpressAuthCode> ExpressAuthCodes;
	typedef HashMap<String, FileExpressContext*> Contexts;
	typedef HashMap<String, FileExpressServoContext*> ServoContexts;
	typedef std::list<FileExpressListener*> ExpressListeners;
	typedef std::vector<FileExpressTask*> ExpressTasks;

	NonblockingAcceptor* mAcceptor;
	char* mReceiveCache;

	SessionRecords mSessionRecords;		/// 会话传输文件记录

	CELL_MUTEX(mContextMutex);
	ServoContexts mServoContexts;
	Contexts mContexts;

	CELL_MUTEX(mAuthMutex);
	ExpressAuthCodes mAuthCodes;

	CELL_MUTEX(mListenerMutex);
	ExpressListeners mExpressListeners;

	ExecutorService* mExecutor;		/// 执行器

	CELL_MUTEX(mTaskMutex);
	ExpressTasks mExpressTasks;		/// 快递任务

	ExpressTaskListener* mTaskListener;
	friend class ExpressTaskListener;
};



/** 快递授权码
 *
 * @author
 *		Jiangwei Xu
 */
class _CellExport ExpressAuthCode : public GeneralAlloc
{
private:
	/** 构造函数。
	*/
	ExpressAuthCode(void);

public:
	/** 构造函数。
	*/
	ExpressAuthCode(const String& path, int auth, uint64 duration = 10 * 60 * 1000);

	/** 构造函数。
	*/
	ExpressAuthCode(const ExpressAuthCode& other);

	/** 析构函数。
	*/
	virtual ~ExpressAuthCode(void);

public:
	/** 权限。
	*/
	enum _Auth
	{
		// 读写
		WRITE = 0,
		// 只读
		READ,
		// 无权限
		NO_ACCESS
	};

	/// 无限有效期
	const static int DURATION_NONE;

	/** 操作符重载。
	*/
	bool operator==(ExpressAuthCode& other) const;
	/** 操作符重载。
	*/
	bool operator==(const ExpressAuthCode& other) const;

	/** 操作符重载。
	*/
	ExpressAuthCode& operator=(ExpressAuthCode& other);

public:
	/** 返回授权码。
	*/
	const String& getCode(void) const;

	/** 设置授权码。
	*/
	void setCode(const String& code);

	/** 返回文件系统上下文路径。
	*/
	const String& getContextPath(void) const;

	/** 返回权限。
	*/
	int getAuth(void) const;

	/** 返回会话上下文有效期长度。
	*/
	uint64 getDuration(void) const;

private:
	/**
	*/
	void setContextPath(const String& path);

	/**
	*/
	void changeAuth(const char* auth) const;

private:
	uint64 mOrigin;
	uint64 mDuration;
	String mCode;
	String mContextPath;
	mutable int mAuth;

	friend class FileExpress;
	friend class FileExpressContext;
	friend class FileExpressTask;
};



/** 任务监听器。
*/
class _CellPrivate ExpressTaskListener : public FileExpressListener, public GeneralAlloc
{
public:
	/**
	*/
	ExpressTaskListener(FileExpress* express);

	/**
	*/
	virtual ~ExpressTaskListener(void);

public:
	/**
	*/
	void expressStarted(FileExpressContext* context);

	/**
	*/
	void expressCompleted(FileExpressContext* context);

	/**
	*/
	void expressProgress(FileExpressContext* context);

	/**
	*/
	void expressError(FileExpressContext* context);

private:
	FileExpress* mExpress;
};

} // end namespace cell

#endif // CellFileExpress_h
